package com.gao.transportapi.controller;

import com.gao.transportapi.common.cache.ApiKeyCache;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * API代理控制器
 * 直接转发请求到目标API，并替换API密钥
 */
@Slf4j
@RestController
@Order(10) // 较低的优先级，确保在AccountController之后处理
public class ProxyController {

    // 硅基流平台类型常量
    private static final String PLATFORM_TYPE_SILICONFLOW = "SILICONFLOW";

    @Value("${silicon.flow.api.base-url}")
    private String targetApiBaseUrl;

    @Resource
    ApiKeyCache apiKeyCache;

    /**
     * 代理所有请求，但排除/accounts路径
     *
     * @param request HTTP请求
     * @param response HTTP响应
     * @throws IOException IO异常
     * @throws URISyntaxException URI语法异常
     */
    @RequestMapping(value = "/**")
    public void proxyRequest(HttpServletRequest request, HttpServletResponse response) {
        
        try {
            // 获取请求路径
            URI uri = new URI(request.getRequestURI());
            String path = uri.getPath();


            // 构建目标URL (针对get请求)
            String query = request.getQueryString();
            String targetUrl = targetApiBaseUrl + path;
            if (query != null && !query.isEmpty() && !query.equals("null")) {
                targetUrl = targetUrl + "?" + query;
            }

            URI targetUri = new URI(targetUrl);
            
            // 获取请求方法
            String methodName = request.getMethod();
            HttpMethod httpMethod;
            try {
                httpMethod = HttpMethod.valueOf(methodName);
            } catch (IllegalArgumentException e) {
                log.error("不支持的HTTP方法: {}", methodName);
                response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
                return;
            }

            log.info("转发请求: {} {}", httpMethod, targetUrl);

            // 创建代理请求，配置超时
            SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
            factory.setConnectTimeout(10000); // 连接超时10秒
            factory.setReadTimeout(300000);   // 读取超时5分钟（适合流式响应）
            
            ClientHttpRequest proxyRequest = factory.createRequest(targetUri, httpMethod);

            // 获取API密钥
            String apiKey = apiKeyCache.getApiKey(PLATFORM_TYPE_SILICONFLOW);
            if (apiKey == null || apiKey.trim().isEmpty()) {
                log.error("无法获取有效的API密钥");
                response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
                response.setContentType("application/json");
                response.getWriter().write("{\"error\":\"无法获取有效的API密钥\"}");
                return;
            }
            apiKey = apiKey.trim();
            log.info("使用API密钥: {}", apiKey.substring(0, Math.min(5, apiKey.length())) + "***");

            // 复制请求头，但替换Authorization头
            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                Enumeration<String> headerValues = request.getHeaders(headerName);
                List<String> values = new ArrayList<>();
                while (headerValues.hasMoreElements()) {
                    values.add(headerValues.nextElement());
                }
                proxyRequest.getHeaders().addAll(headerName, values);
            }

            // 设置Authorization头为API密钥
            proxyRequest.getHeaders().set("Authorization", "Bearer " + apiKey);

            // 复制请求体
            StreamUtils.copy(request.getInputStream(), proxyRequest.getBody());

            // 执行远程调用
            ClientHttpResponse proxyResponse = proxyRequest.execute();
            // 设置响应状态码
            response.setStatus(proxyResponse.getStatusCode().value());

            // 标记API密钥已使用并异步检查余额
            apiKeyCache.markKeyAsUsed(apiKey);

            // 设置响应头
            proxyResponse.getHeaders().forEach((key, value) -> value.forEach(it -> {
                response.setHeader(key, it);
            }));
            
            // 禁用响应缓冲，实现真正的流式传输
            response.setBufferSize(512); // 设置小的缓冲区
            
            // 流式复制数据 - 逐块传输，支持实时流式响应
            byte[] buffer = new byte[1024]; // 1KB缓冲区，实现快速传输
            int bytesRead;
            java.io.InputStream inputStream = proxyResponse.getBody();
            java.io.OutputStream outputStream = response.getOutputStream();
            
            try {
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    // 检查客户端是否断开连接
                    if (response.isCommitted()) {
                        try {
                            outputStream.write(buffer, 0, bytesRead);
                            outputStream.flush(); // 立即刷新，确保数据实时发送
                        } catch (IOException e) {
                            // 客户端断开连接
                            log.warn("客户端断开连接，停止传输: {}", targetUrl);
                            break;
                        }
                    } else {
                        outputStream.write(buffer, 0, bytesRead);
                        outputStream.flush();
                    }
                }
            } finally {
                // 确保关闭输入流
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("关闭输入流失败", e);
                }
            }

            log.info("请求转发完成: {}, 状态码: {}", targetUrl, proxyResponse.getStatusCode());

        } catch (Exception e) {
            log.error("转发请求失败", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            response.setContentType("application/json;charset=UTF-8");
            try {
                response.getWriter().write("{\"error\":\"转发请求失败: " + e.getMessage().replaceAll("\"", "\\\\\"") + "\"}");
            } catch (IOException ioException) {
                log.error("写入错误响应失败", ioException);
            }
        }
    }
}